package com.zt.securityTest.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zt.securityTest.common.R;
import com.zt.securityTest.entity.LoginUser;
import com.zt.securityTest.entity.User;
import com.zt.securityTest.mapper.UserMapper;
import com.zt.securityTest.service.UserService;
import com.zt.securityTest.utils.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.zt.securityTest.common.ResultCode.*;
import static com.zt.securityTest.filter.JwtAuthenticationTokenFilter.TOKEN_KEY;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public R login(User user) {
        //将用户名和密码封装成Autnentication对象
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
        //通过authenticationManager的authenticate方法进行用户认证
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //认证不通过返回自定义异常
        if (ObjectUtil.isNull(authenticate)){
            throw new RuntimeException(LOGOUT_FAILURE.getMsg());
        }
        //认证通过，则使用认证后的对象的getPrincipal方法获取到LoginUser对象
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        //生成jwt，使用fastjson将loginUser对象转成字符串
        String loginUserString = JSON.toJSONString(loginUser);
        Long userId = loginUser.getUser().getId();
        //调用工具类生成jwt令牌
        String jwt = JwtUtil.createJWT(userId.toString(), loginUserString, null);

        String key = TOKEN_KEY+jwt;
        redisTemplate.opsForValue().set(key,jwt,5, TimeUnit.MINUTES);

        System.out.println("Thread: "+Thread.currentThread().getId());

        Map<String, Object> map = new HashMap<>();
        map.put("token",jwt);
        map.put("username",loginUser.getUsername());

        if (!map.get("token").equals("") && !map.get("username").equals("")){
            return R.ok().code(LOGIN_SUCCESS.getCode()).message(LOGIN_SUCCESS.getMsg()).data("map",map);
        }
        return R.error().code(LOGIN_FAILURE.getCode()).message(LOGIN_FAILURE.getMsg());

    }

    @Override
    public R logout(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("Authorization");
        //如果token不存在(第一次：从header中查找)
        if (!StringUtils.hasText(token)){
            token = request.getParameter("Authorization");
        }

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null){
            //1.清除上下文
            new SecurityContextLogoutHandler().logout(request,response,authentication);
            redisTemplate.delete(TOKEN_KEY+token);
        }
        return R.ok().code(LOGOUT_SUCCESS.getCode()).message(LOGOUT_SUCCESS.getMsg());
    }
}
